﻿/**
* ...
* @author Default
*/

package hails;

import hails.util.StringUtil;
import php.Exception;
import php.Lib;
import php.Web;

// ControllerConfig should import all controllers, just to make them compile...
// (Because if there are no references (as they are loaded dynamically) they're not compiled.
import config.ControllerConfig;

//
class HailsDispatcher {

	/*public function new() {
		
	}*/
	
	static var controllerClassPrefix:String = "controller.";
	
	static function getUriPart(n:Int) : String {
		var s:Array < String > = Web.getURI().split("/");
		if (s != null && s.length > n) {
			return s[n];
		}
		return null;
	}
	
	static function getScriptName() : String {
		return getUriPart(1);
		//return getUriPart(2);
	}
	
	static function getControllerUri() : String {
		return getUriPart(2);
		//return getUriPart(3);
	}
	
	static function getActionUri() : String {
		return getUriPart(3);
		//return getUriPart(4);
	}
	
	static function getControllerName() {
		var s = getControllerUri();
		if (s != null) {
			s = StringUtil.camelize(s) + "Controller";
		}
		return s;
	}
	
	static var overriddenAction:String = null;
	static function getActionName() {
		if (overriddenAction != null) {
			return overriddenAction;
		}
		var s = getActionUri();
		if (s != null && s != "") {
			s = StringUtil.camelizeWithFirstAsLower(s);
		} else {
			return "index";
		}
		return s;
	}
	
	static function pageNotFound(s:String) : Void {
		Web.setReturnCode(404);
		Lib.print("404 Page don't exist - " + s);		
	}
	
	static var urlParam = null;
	
	static function figureRoute() : Route {
		var method:String = Web.getMethod().toUpperCase();
		if (method == 'POST') {
			var methodParam:Array < String > = Web.getParamValues('_method');
			if (methodParam != null && methodParam.length > 0) {
				method = methodParam[1].toUpperCase();
			}
		}
		var actionName = getActionName();
		urlParam = actionName;
		if (method == 'POST') {
			if (actionName != null) {
				return Route.post_param(actionName);
			} else {
				return Route.post;
			}
		} else if (method == 'GET') {
			if (actionName != null) {
				return Route.get_param(actionName);
			} else {
				return Route.get;
			}
		} else if (method == 'DELETE') {
			if (actionName != null) {
				return Route.delete_param(actionName);
			}
		}/* else if (method == 'PUT') {
			if (actionName != null) {
				return Route.get_param(actionName);
			} else {
				return Route.get;
			}
		}*/
		return null;
	}
	
	public static function handleRequest() : Void {
		var params:Hash<String> = Web.getParams();
		var actionName:String = getActionName();
		if (StringTools.startsWith(actionName, "_")) {
			pageNotFound("BAD");
			return;
		}
		var controllerId = getControllerUri();
		var fullControllerName = controllerClassPrefix + getControllerName();
		var controllerClass:Class<Dynamic> = Type.resolveClass(fullControllerName);
		if (controllerClass != null) {
			var controller:HailsController = Type.createInstance(controllerClass, [actionName]);
			//if (Reflect.hasField(controller, 'actions')) {
			//	var actions:Dynamic = Reflect.field(controller, 'actions');
			//	
			//}
			var actionFound = false;
			var actionMethodName = "action_" + actionName;
			if (Reflect.hasField(controller, actionMethodName)) {
				actionFound = true;
			} else {
				var route = figureRoute();
				if (route != null) {
					actionMethodName = controller.route(route);
					if (actionMethodName != null) {
						if (Reflect.hasField(controller, actionMethodName)) {
							controller.initialAction = actionMethodName;
							trace(actionMethodName);
							controller.urlParam = urlParam;
							actionFound = true;
						}
					}
				}
			}
			if (actionFound) {
				var actionMethod = Reflect.field(controller, actionMethodName);
				trace(actionMethod);
				if (Reflect.isFunction(actionMethod)) {
					var hasError = false;
					var theError:Dynamic;
					try {
						//trace("before CALLMETHOD");
						var hc:HailsController = controller;
						hc.controllerId = controllerId;
						Reflect.callMethod(hc, actionMethod, []); // []);
						overriddenAction = hc.initialAction;
						//trace("after CALLMETHOD");
						if (!hc.hasRendered && hc.shouldRender) {
							doRender(hc);						
						}
						return;
					} catch (err:Dynamic) {
						hasError = true;
						theError = err;
					}
					HailsDbRecord.closeConnection(); // close sql-connection if open
					if (hasError) {
						throw theError;
					}
				}
			}
		}
		//pageNotFound(fullControllerName);
	}
	
	static function doRender(hc:HailsController) {
		if (hc.renderType == "php") {
			new HailsViewPhp(hc, getControllerUri(), getActionName()).render();
		} else if (hc.renderType == "html") {
			hc.render();
		} else {
			throw new Exception("Unknown rendertype: " + hc.renderType);
		}
	}
}